/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef jit_x86_shared_CodeGenerator_x86_shared_h#define jit_x86_shared_CodeGenerator_x86_shared_h#include"jit/shared/CodeGenerator-shared.h"namespacejs{namespacejit{classOutOfLineBailout;classOutOfLineUndoALUOperation;classOutOfLineLoadTypedArrayOutOfBounds;classMulNegativeZeroCheck;classModOverflowCheck;classReturnZero;classOutOfLineTableSwitch;classCodeGeneratorX86Shared:publicCodeGeneratorShared{friendclassMoveResolverX86;CodeGeneratorX86Shared*thisFromCtor(){returnthis;}template<typenameT>voidbailout(constT&t,LSnapshot*snapshot);protected:// Load a NaN or zero into a register for an out of bounds AsmJS or static// typed array load.classOutOfLineLoadTypedArrayOutOfBounds:publicOutOfLineCodeBase<CodeGeneratorX86Shared>{AnyRegisterdest_;Scalar::TypeviewType_;public:OutOfLineLoadTypedArrayOutOfBounds(AnyRegisterdest,Scalar::TypeviewType):dest_(dest),viewType_(viewType){}AnyRegisterdest()const{returndest_;}Scalar::TypeviewType()const{returnviewType_;}voidaccept(CodeGeneratorX86Shared*codegen){codegen->visitOutOfLineLoadTypedArrayOutOfBounds(this);}};// Additional bounds check for vector Float to Int conversion, when the// undefined pattern is seen. Might imply a bailout.classOutOfLineSimdFloatToIntCheck:publicOutOfLineCodeBase<CodeGeneratorX86Shared>{Registertemp_;FloatRegisterinput_;LInstruction*ins_;wasm::BytecodeOffsetbytecodeOffset_;public:OutOfLineSimdFloatToIntCheck(Registertemp,FloatRegisterinput,LInstruction*ins,wasm::BytecodeOffsetbytecodeOffset):temp_(temp),input_(input),ins_(ins),bytecodeOffset_(bytecodeOffset){}Registertemp()const{returntemp_;}FloatRegisterinput()const{returninput_;}LInstruction*ins()const{returnins_;}wasm::BytecodeOffsetbytecodeOffset()const{returnbytecodeOffset_;}voidaccept(CodeGeneratorX86Shared*codegen){codegen->visitOutOfLineSimdFloatToIntCheck(this);}};public:NonAssertingLabeldeoptLabel_;OperandToOperand(constLAllocation&a);OperandToOperand(constLAllocation*a);OperandToOperand(constLDefinition*def);#ifdef JS_PUNBOX64OperandToOperandOrRegister64(constLInt64Allocationinput);#elseRegister64ToOperandOrRegister64(constLInt64Allocationinput);#endifMoveOperandtoMoveOperand(LAllocationa)const;voidbailoutIf(Assembler::Conditioncondition,LSnapshot*snapshot);voidbailoutIf(Assembler::DoubleConditioncondition,LSnapshot*snapshot);voidbailoutFrom(Label*label,LSnapshot*snapshot);voidbailout(LSnapshot*snapshot);template<typenameT1,typenameT2>voidbailoutCmpPtr(Assembler::Conditionc,T1lhs,T2rhs,LSnapshot*snapshot){masm.cmpPtr(lhs,rhs);bailoutIf(c,snapshot);}voidbailoutTestPtr(Assembler::Conditionc,Registerlhs,Registerrhs,LSnapshot*snapshot){masm.testPtr(lhs,rhs);bailoutIf(c,snapshot);}template<typenameT1,typenameT2>voidbailoutCmp32(Assembler::Conditionc,T1lhs,T2rhs,LSnapshot*snapshot){masm.cmp32(lhs,rhs);bailoutIf(c,snapshot);}template<typenameT1,typenameT2>voidbailoutTest32(Assembler::Conditionc,T1lhs,T2rhs,LSnapshot*snapshot){masm.test32(lhs,rhs);bailoutIf(c,snapshot);}voidbailoutIfFalseBool(Registerreg,LSnapshot*snapshot){masm.test32(reg,Imm32(0xFF));bailoutIf(Assembler::Zero,snapshot);}voidbailoutCvttsd2si(FloatRegistersrc,Registerdest,LSnapshot*snapshot){// vcvttsd2si returns 0x80000000 on failure. Test for it by// subtracting 1 and testing overflow. The other possibility is to test// equality for INT_MIN after a comparison, but 1 costs fewer bytes to// materialize.masm.vcvttsd2si(src,dest);masm.cmp32(dest,Imm32(1));bailoutIf(Assembler::Overflow,snapshot);}voidbailoutCvttss2si(FloatRegistersrc,Registerdest,LSnapshot*snapshot){// Same trick as explained in the above comment.masm.vcvttss2si(src,dest);masm.cmp32(dest,Imm32(1));bailoutIf(Assembler::Overflow,snapshot);}protected:boolgenerateOutOfLineCode();voidemitCompare(MCompare::CompareTypetype,constLAllocation*left,constLAllocation*right);// Emits a branch that directs control flow to the true block if |cond| is// true, and the false block if |cond| is false.voidemitBranch(Assembler::Conditioncond,MBasicBlock*ifTrue,MBasicBlock*ifFalse,Assembler::NaNCondifNaN=Assembler::NaN_HandledByCond);voidemitBranch(Assembler::DoubleConditioncond,MBasicBlock*ifTrue,MBasicBlock*ifFalse);voidtestNullEmitBranch(Assembler::Conditioncond,constValueOperand&value,MBasicBlock*ifTrue,MBasicBlock*ifFalse){cond=masm.testNull(cond,value);emitBranch(cond,ifTrue,ifFalse);}voidtestUndefinedEmitBranch(Assembler::Conditioncond,constValueOperand&value,MBasicBlock*ifTrue,MBasicBlock*ifFalse){cond=masm.testUndefined(cond,value);emitBranch(cond,ifTrue,ifFalse);}voidtestObjectEmitBranch(Assembler::Conditioncond,constValueOperand&value,MBasicBlock*ifTrue,MBasicBlock*ifFalse){cond=masm.testObject(cond,value);emitBranch(cond,ifTrue,ifFalse);}voidtestZeroEmitBranch(Assembler::Conditioncond,Registerreg,MBasicBlock*ifTrue,MBasicBlock*ifFalse){MOZ_ASSERT(cond==Assembler::Equal||cond==Assembler::NotEqual);masm.cmpPtr(reg,ImmWord(0));emitBranch(cond,ifTrue,ifFalse);}voidemitTableSwitchDispatch(MTableSwitch*mir,Registerindex,Registerbase);voidemitSimdExtractLane8x16(FloatRegisterinput,Registeroutput,unsignedlane,SimdSignsignedness);voidemitSimdExtractLane16x8(FloatRegisterinput,Registeroutput,unsignedlane,SimdSignsignedness);voidemitSimdExtractLane32x4(FloatRegisterinput,Registeroutput,unsignedlane);public:CodeGeneratorX86Shared(MIRGenerator*gen,LIRGraph*graph,MacroAssembler*masm);public:// Instruction visitors.virtualvoidvisitDouble(LDouble*ins);virtualvoidvisitFloat32(LFloat32*ins);virtualvoidvisitMinMaxD(LMinMaxD*ins);virtualvoidvisitMinMaxF(LMinMaxF*ins);virtualvoidvisitAbsD(LAbsD*ins);virtualvoidvisitAbsF(LAbsF*ins);virtualvoidvisitClzI(LClzI*ins);virtualvoidvisitCtzI(LCtzI*ins);virtualvoidvisitPopcntI(LPopcntI*ins);virtualvoidvisitPopcntI64(LPopcntI64*lir);virtualvoidvisitSqrtD(LSqrtD*ins);virtualvoidvisitSqrtF(LSqrtF*ins);virtualvoidvisitPowHalfD(LPowHalfD*ins);virtualvoidvisitAddI(LAddI*ins);virtualvoidvisitAddI64(LAddI64*ins);virtualvoidvisitSubI(LSubI*ins);virtualvoidvisitSubI64(LSubI64*ins);virtualvoidvisitMulI(LMulI*ins);virtualvoidvisitMulI64(LMulI64*ins);virtualvoidvisitDivI(LDivI*ins);virtualvoidvisitDivPowTwoI(LDivPowTwoI*ins);virtualvoidvisitDivOrModConstantI(LDivOrModConstantI*ins);virtualvoidvisitModI(LModI*ins);virtualvoidvisitModPowTwoI(LModPowTwoI*ins);virtualvoidvisitBitNotI(LBitNotI*ins);virtualvoidvisitBitOpI(LBitOpI*ins);virtualvoidvisitBitOpI64(LBitOpI64*ins);virtualvoidvisitShiftI(LShiftI*ins);virtualvoidvisitShiftI64(LShiftI64*ins);virtualvoidvisitUrshD(LUrshD*ins);virtualvoidvisitTestIAndBranch(LTestIAndBranch*test);virtualvoidvisitTestDAndBranch(LTestDAndBranch*test);virtualvoidvisitTestFAndBranch(LTestFAndBranch*test);virtualvoidvisitCompare(LCompare*comp);virtualvoidvisitCompareAndBranch(LCompareAndBranch*comp);virtualvoidvisitCompareD(LCompareD*comp);virtualvoidvisitCompareDAndBranch(LCompareDAndBranch*comp);virtualvoidvisitCompareF(LCompareF*comp);virtualvoidvisitCompareFAndBranch(LCompareFAndBranch*comp);virtualvoidvisitBitAndAndBranch(LBitAndAndBranch*baab);virtualvoidvisitNotI(LNotI*comp);virtualvoidvisitNotD(LNotD*comp);virtualvoidvisitNotF(LNotF*comp);virtualvoidvisitMathD(LMathD*math);virtualvoidvisitMathF(LMathF*math);virtualvoidvisitFloor(LFloor*lir);virtualvoidvisitFloorF(LFloorF*lir);virtualvoidvisitCeil(LCeil*lir);virtualvoidvisitCeilF(LCeilF*lir);virtualvoidvisitRound(LRound*lir);virtualvoidvisitRoundF(LRoundF*lir);virtualvoidvisitNearbyInt(LNearbyInt*lir);virtualvoidvisitNearbyIntF(LNearbyIntF*lir);virtualvoidvisitGuardShape(LGuardShape*guard);virtualvoidvisitGuardObjectGroup(LGuardObjectGroup*guard);virtualvoidvisitGuardClass(LGuardClass*guard);virtualvoidvisitEffectiveAddress(LEffectiveAddress*ins);virtualvoidvisitUDivOrMod(LUDivOrMod*ins);virtualvoidvisitUDivOrModConstant(LUDivOrModConstant*ins);virtualvoidvisitWasmStackArg(LWasmStackArg*ins);virtualvoidvisitWasmStackArgI64(LWasmStackArgI64*ins);virtualvoidvisitWasmSelect(LWasmSelect*ins);virtualvoidvisitWasmReinterpret(LWasmReinterpret*lir);virtualvoidvisitMemoryBarrier(LMemoryBarrier*ins);virtualvoidvisitWasmAddOffset(LWasmAddOffset*lir);virtualvoidvisitWasmTruncateToInt32(LWasmTruncateToInt32*lir);virtualvoidvisitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop*lir);virtualvoidvisitAtomicTypedArrayElementBinopForEffect(LAtomicTypedArrayElementBinopForEffect*lir);virtualvoidvisitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement*lir);virtualvoidvisitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement*lir);virtualvoidvisitCopySignD(LCopySignD*lir);virtualvoidvisitCopySignF(LCopySignF*lir);virtualvoidvisitRotateI64(LRotateI64*lir);voidvisitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds*ool);voidvisitNegI(LNegI*lir);voidvisitNegD(LNegD*lir);voidvisitNegF(LNegF*lir);voidvisitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck*ool);// SIMD operatorsvoidvisitSimdValueInt32x4(LSimdValueInt32x4*lir);voidvisitSimdValueFloat32x4(LSimdValueFloat32x4*lir);voidvisitSimdSplatX16(LSimdSplatX16*lir);voidvisitSimdSplatX8(LSimdSplatX8*lir);voidvisitSimdSplatX4(LSimdSplatX4*lir);voidvisitSimd128Int(LSimd128Int*ins);voidvisitSimd128Float(LSimd128Float*ins);voidvisitInt32x4ToFloat32x4(LInt32x4ToFloat32x4*ins);voidvisitFloat32x4ToInt32x4(LFloat32x4ToInt32x4*ins);voidvisitFloat32x4ToUint32x4(LFloat32x4ToUint32x4*ins);voidvisitSimdReinterpretCast(LSimdReinterpretCast*lir);voidvisitSimdExtractElementB(LSimdExtractElementB*lir);voidvisitSimdExtractElementI(LSimdExtractElementI*lir);voidvisitSimdExtractElementU2D(LSimdExtractElementU2D*lir);voidvisitSimdExtractElementF(LSimdExtractElementF*lir);voidvisitSimdInsertElementI(LSimdInsertElementI*lir);voidvisitSimdInsertElementF(LSimdInsertElementF*lir);voidvisitSimdSwizzleI(LSimdSwizzleI*lir);voidvisitSimdSwizzleF(LSimdSwizzleF*lir);voidvisitSimdShuffleX4(LSimdShuffleX4*lir);voidvisitSimdShuffle(LSimdShuffle*lir);voidvisitSimdUnaryArithIx16(LSimdUnaryArithIx16*lir);voidvisitSimdUnaryArithIx8(LSimdUnaryArithIx8*lir);voidvisitSimdUnaryArithIx4(LSimdUnaryArithIx4*lir);voidvisitSimdUnaryArithFx4(LSimdUnaryArithFx4*lir);voidvisitSimdBinaryCompIx16(LSimdBinaryCompIx16*lir);voidvisitSimdBinaryCompIx8(LSimdBinaryCompIx8*lir);voidvisitSimdBinaryCompIx4(LSimdBinaryCompIx4*lir);voidvisitSimdBinaryCompFx4(LSimdBinaryCompFx4*lir);voidvisitSimdBinaryArithIx16(LSimdBinaryArithIx16*lir);voidvisitSimdBinaryArithIx8(LSimdBinaryArithIx8*lir);voidvisitSimdBinaryArithIx4(LSimdBinaryArithIx4*lir);voidvisitSimdBinaryArithFx4(LSimdBinaryArithFx4*lir);voidvisitSimdBinarySaturating(LSimdBinarySaturating*lir);voidvisitSimdBinaryBitwise(LSimdBinaryBitwise*lir);voidvisitSimdShift(LSimdShift*lir);voidvisitSimdSelect(LSimdSelect*ins);voidvisitSimdAllTrue(LSimdAllTrue*ins);voidvisitSimdAnyTrue(LSimdAnyTrue*ins);template<classT,classReg>voidvisitSimdGeneralShuffle(LSimdGeneralShuffleBase*lir,Regtemp);voidvisitSimdGeneralShuffleI(LSimdGeneralShuffleI*lir);voidvisitSimdGeneralShuffleF(LSimdGeneralShuffleF*lir);// Out of line visitors.voidvisitOutOfLineBailout(OutOfLineBailout*ool);voidvisitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation*ool);voidvisitMulNegativeZeroCheck(MulNegativeZeroCheck*ool);voidvisitModOverflowCheck(ModOverflowCheck*ool);voidvisitReturnZero(ReturnZero*ool);voidvisitOutOfLineTableSwitch(OutOfLineTableSwitch*ool);voidvisitOutOfLineSimdFloatToIntCheck(OutOfLineSimdFloatToIntCheck*ool);voidgenerateInvalidateEpilogue();// Generating a result.template<typenameS,typenameT>voidatomicBinopToTypedIntArray(AtomicOpop,Scalar::TypearrayType,constS&value,constT&mem,Registertemp1,Registertemp2,AnyRegisteroutput);// Generating no result.template<typenameS,typenameT>voidatomicBinopToTypedIntArray(AtomicOpop,Scalar::TypearrayType,constS&value,constT&mem);voidsetReturnDoubleRegs(LiveRegisterSet*regs);voidcanonicalizeIfDeterministic(Scalar::Typetype,constLAllocation*value);};// An out-of-line bailout thunk.classOutOfLineBailout:publicOutOfLineCodeBase<CodeGeneratorX86Shared>{LSnapshot*snapshot_;public:explicitOutOfLineBailout(LSnapshot*snapshot):snapshot_(snapshot){}voidaccept(CodeGeneratorX86Shared*codegen);LSnapshot*snapshot()const{returnsnapshot_;}};}// namespace jit}// namespace js#endif /* jit_x86_shared_CodeGenerator_x86_shared_h */